/*
    解题思路：
    1. 注意，循环队列底层空间大小是固定的
    2. 采用计数方式实现队列空或者满的判断
    3. 入队列时：队列可能满，往队尾插入，注意back在末尾特殊情况
    4. 出队列时：队列可能空，删除队头元素，注意front可能在队尾
    5. 获取队头注意空队列时返回-1
    6. 获取队尾时，注意back-1可能为负数，队尾元素下标：
       (back-1+array.length)%array.length
*/
class MyCircularQueue {
    int[] array;
    int front;   // 队头
    int back;    // 队尾
    int count;   // 队列中有效元素个数
    public MyCircularQueue(int k) {
        array = new int[k];
    }
    
    public boolean enQueue(int value) {
        if(isFull()){
            return false;
        }

        // 在队尾插入一个元素，然后back往后移动
        array[back] = value;
        back++;

        // back往后移动之后，可能会来到空间末尾
        // 此时将back挪到空间起始位置
        if(back == array.length){
            back = 0;
        }

        count++;
        return true;
    }
    
    public boolean deQueue() {
        if(isEmpty()){
            return false;
        }

        // 出队列，队头往后移动
        ++front;

        // 队头往后移动之后也可能会来到空间末尾
        // 此时需要挪到空间起始位置
        front %= array.length;
        --count;
        return true;
    }
    
    public int Front() {
        if(isEmpty()){
            return -1;
        }

        // 如果队列不空，说明队列中有元素，队头元素直接返回front即可
        return array[front];
    }
    
    public int Rear() {
        if(isEmpty()){
            return -1;
        }

        // 如果队列不空，说明队列中有元素
        // 队尾元素即：back-1,
        // 如果back不在0号位置，back-1就是队尾元素下标
        // 如果back在0号位置，-1之后就是负数，因此需要+数组长度
        // 两个结合起来：
        return array[(back - 1 + array.length)%array.length];
    }
    
    public boolean isEmpty() {
        return 0 == count;
    }
    
    public boolean isFull() {
        return count == array.length;
    }
}